home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / MTHROWU.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  13KB  |  500 lines

  1. /*    SCCS Id: @(#)mthrowu.c    3.0    89/11/22
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include    "hack.h"
  6.  
  7. STATIC_DCL int FDECL(movedist,(int,int,int,int));
  8. STATIC_DCL void FDECL(drop_throw,(struct obj *,BOOLEAN_P,int,int));
  9. STATIC_DCL void FDECL(m_throw,(int,int,int,int,int,struct obj *));
  10.  
  11. #define URETREATING(x,y) (movedist(u.ux,u.uy,x,y) > movedist(u.ux0,u.uy0,x,y))
  12.  
  13. boolean FDECL(lined_up, (struct monst *));
  14.  
  15. #ifndef OVLB
  16.  
  17. STATIC_DCL const char *breathwep[];
  18.  
  19. #else /* OVLB */
  20.  
  21. schar NEARDATA tbx = 0, NEARDATA tby = 0;
  22.     /* used for direction of throw, buzz, etc. */
  23.  
  24. STATIC_OVL const char NEARDATA *breathwep[] = {    "fragments",
  25.                 "fire",
  26.                 "sleep gas",
  27.                 "frost",
  28.                 "death",
  29.                 "lightning",
  30.                 "poison gas",
  31.                 "acid"
  32. };
  33.  
  34. int
  35. thitu(tlev, dam, obj, name)    /* u is hit by sth, but not a monster */
  36.     register int tlev, dam;
  37.     struct obj *obj;
  38.     register const char *name;
  39. {
  40.     const char *onm = an(name);
  41.     boolean is_acid = (obj && obj->otyp == ACID_VENOM);
  42.  
  43.     if(u.uac + tlev <= rnd(20)) {
  44.         if(Blind || !flags.verbose) pline("It misses.");
  45.         else You("are almost hit by %s!", onm);
  46.         return(0);
  47.     } else {
  48.         if(Blind || !flags.verbose) You("are hit!");
  49.         else You("are hit by %s!", onm);
  50. #ifdef POLYSELF
  51.         if (obj && obj->otyp == SILVER_ARROW && (u.ulycn != -1 ||
  52.                 is_demon(uasmon) || u.usym == S_VAMPIRE ||
  53.                 (u.usym == S_IMP && u.umonnum != PM_TENGU))) {
  54.             dam += rnd(20);
  55.             pline("The %sarrow sears your flesh!",
  56.                 Blind ? "" : "silver ");
  57.         }
  58.         if (is_acid && resists_acid(uasmon))
  59.             pline("It doesn't seem to hurt you.");
  60.         else {
  61. #endif
  62.             if (is_acid) pline("It burns!");
  63.             losehp(dam, name, KILLED_BY_AN);
  64. #ifdef POLYSELF
  65.         }
  66. #endif
  67.         return(1);
  68.     }
  69. }
  70.  
  71. /* Be sure this corresponds with what happens to player-thrown objects in
  72.  * dothrow.c (for consistency). --KAA
  73.  */
  74.  
  75. STATIC_OVL void
  76. drop_throw(obj, ohit, x, y)
  77. register struct obj *obj;
  78. boolean ohit;
  79. int x,y;
  80. {
  81.     int create;
  82.  
  83.     if (obj->otyp == CREAM_PIE || obj->olet == VENOM_SYM)
  84.         create = 0;
  85.     else if (ohit &&
  86.          ((obj->otyp >= ARROW && obj->otyp <= SHURIKEN) ||
  87.           obj->otyp == ROCK))
  88.         create = !rn2(3);
  89.     else create = 1;
  90.     if (create && !flooreffects(obj,x,y)) {
  91.         place_object(obj, x, y);
  92.         obj->nobj = fobj;
  93.         fobj = obj;
  94.         stackobj(fobj);
  95.     } else free((genericptr_t)obj);
  96. }
  97.  
  98. #endif /* OVLB */
  99. #ifdef OVL1
  100.  
  101. STATIC_OVL void
  102. m_throw(x, y, dx, dy, range, obj)
  103.     register int x,y,dx,dy,range;        /* direction and range */
  104.     register struct obj *obj;
  105. {
  106.     register struct monst *mtmp;
  107.     struct obj *singleobj;
  108.     char sym = obj->olet;
  109.     int damage;
  110.     int hitu, blindinc=0;
  111.  
  112.     bhitpos.x = x;
  113.     bhitpos.y = y;
  114.  
  115.     singleobj = splitobj(obj, (int)obj->quan-1);
  116.     /* splitobj leaves the new object in the chain (i.e. the monster's
  117.      * inventory).  Remove it.  We can do this in 1 line, but it's highly
  118.      * dependent on the fact that we know splitobj() places it immediately
  119.      * after obj.
  120.      */
  121.     obj->nobj = singleobj->nobj;
  122.  
  123.     if(sym) {
  124.         tmp_at(-1, sym);    /* open call */
  125. #ifdef TEXTCOLOR
  126.         tmp_at(-3, (int)objects[obj->otyp].oc_color);
  127. #else
  128.         tmp_at(-3, (int)AT_OBJ);
  129. #endif
  130.     }
  131.     while(range-- > 0) { /* Actually the loop is always exited by break */
  132.         boolean vis;
  133.  
  134.         bhitpos.x += dx;
  135.         bhitpos.y += dy;
  136.         vis = cansee(bhitpos.x, bhitpos.y);
  137.         if(MON_AT(bhitpos.x, bhitpos.y)) {
  138.             mtmp = m_at(bhitpos.x,bhitpos.y);
  139.  
  140.             if(mtmp->data->ac + 8 + obj->spe <= rnd(20)) {
  141.             if (!vis) pline("It is missed.");
  142.             else miss(distant_name(singleobj,xname), mtmp);
  143.             if (!range) { /* Last position; object drops */
  144.                 drop_throw(singleobj, 0, mtmp->mx, mtmp->my);
  145.                 break;
  146.             }
  147.             } else {
  148.             damage = dmgval(obj, mtmp->data);
  149.             if (damage < 1) damage = 1;
  150.             if (obj->otyp==ACID_VENOM && resists_acid(mtmp->data))
  151.                 damage = 0;
  152.             if (!vis) pline("It is hit%s", exclam(damage));
  153.             else hit(distant_name(singleobj,xname),
  154.                             mtmp,exclam(damage));
  155.             if (obj->opoisoned) {
  156.                 if (resists_poison(mtmp->data)) {
  157.                 if (vis)
  158.                   pline("The poison doesn't seem to affect %s.",
  159.                                 mon_nam(mtmp));
  160.                 } else {
  161.                 if (rn2(30)) damage += rnd(6);
  162.                 else {
  163.                     if (vis)
  164.                     pline("The poison was deadly...");
  165.                     damage = mtmp->mhp;
  166.                 }
  167.                 }
  168.             }
  169.             if (obj->otyp==SILVER_ARROW && (is_were(mtmp->data)
  170.                 || is_demon(mtmp->data)
  171.                 || mtmp->data->mlet == S_VAMPIRE
  172.                 || (mtmp->data->mlet==S_IMP
  173.                     && mtmp->data != &mons[PM_TENGU]))) {
  174.                 if (vis) pline("The silver arrow sears %s's flesh!",
  175.                 mon_nam(mtmp));
  176.                 else pline("Its flesh is seared!");
  177.                 damage += rnd(20);
  178.             }
  179.             if (obj->otyp==ACID_VENOM && cansee(mtmp->mx,mtmp->my)){
  180.                 if (resists_acid(mtmp->data)) {
  181.                 pline("%s is unaffected.", vis ? Monnam(mtmp)
  182.                     : "It");
  183.                 damage = 0;
  184.                 } else if (vis)
  185.                 pline("The acid burns %s!", mon_nam(mtmp));
  186.                 else pline("It is burned!");
  187.             }
  188.             mtmp->mhp -= damage;
  189.             if(mtmp->mhp < 1) {
  190.                 pline("%s is %s!", vis ? Monnam(mtmp) : "It",
  191.                    (is_demon(mtmp->data) || 
  192.                     is_undead(mtmp->data) || !vis) ?
  193.                  "destroyed" : "killed");
  194.                 mondied(mtmp);
  195.             }
  196.  
  197.             if((obj->otyp == CREAM_PIE) ||
  198.                (obj->otyp == BLINDING_VENOM)) {
  199.                 if (vis)
  200.                 pline("%s is blinded by the %s.",
  201.                       Monnam(mtmp), xname(singleobj));
  202.                 if(mtmp->msleep) mtmp->msleep = 0;
  203.                 mtmp->mcansee = 0;
  204.                 {
  205.                 register unsigned rnd_tmp = rnd(25) + 20;
  206.                 if((mtmp->mblinded + rnd_tmp) > 127)
  207.                     mtmp->mblinded = 127;
  208.                 else mtmp->mblinded += rnd_tmp;
  209.                 }
  210.             }
  211.             drop_throw(singleobj, 1, bhitpos.x, bhitpos.y);
  212.             break;
  213.             }
  214.         }
  215.         if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
  216.             if (multi) nomul(0);
  217.  
  218.             switch(obj->otyp) {
  219.                 int dam;
  220.                 case CREAM_PIE:
  221.                 case BLINDING_VENOM:
  222.                 hitu = thitu(8, 0, singleobj, xname(singleobj));
  223.                 break;
  224.                 default:
  225.                 dam = dmgval(obj, uasmon);
  226.                 if (dam < 1) dam = 1;
  227.                 hitu = thitu(8+obj->spe, dam, singleobj,
  228.                     xname(singleobj));
  229.             }
  230.             if (hitu && obj->opoisoned)
  231.                 /* it's safe to call xname twice because it's the
  232.                    same object both times... */
  233.                 poisoned(xname(singleobj), A_STR, xname(singleobj), 10);
  234.             if(hitu && (obj->otyp == CREAM_PIE ||
  235.                      obj->otyp == BLINDING_VENOM)) {
  236.                 blindinc = rnd(25);
  237.                 if(obj->otyp == CREAM_PIE) {
  238.                 if(!Blind) pline("Yecch!  You've been creamed.");
  239.                 else    pline("There's something sticky all over your %s.", body_part(FACE));
  240.                 } else {    /* venom in the eyes */
  241.                 if(Blindfolded) /* nothing */ ;
  242.                 else if(!Blind) pline("The venom blinds you.");
  243.                 else    Your("%s sting.",
  244.                     makeplural(body_part(EYE)));
  245.                 }
  246.             }
  247.             stop_occupation();
  248.             if (hitu || !range) {
  249.                 drop_throw(singleobj, hitu, u.ux, u.uy);
  250.                 break;
  251.             }
  252.         } else if (!range    /* reached end of path */
  253.             /* missile hits edge of screen */
  254.             || !isok(bhitpos.x+dx,bhitpos.y+dy)
  255.             /* missile hits the wall */
  256.             || IS_WALL(levl[bhitpos.x+dx][bhitpos.y+dy].typ)
  257.             || levl[bhitpos.x+dx][bhitpos.y+dy].typ == SDOOR
  258.             || levl[bhitpos.x+dx][bhitpos.y+dy].typ == SCORR
  259. #ifdef SINKS
  260.             /* Thrown objects "sink" */
  261.             || IS_SINK(levl[bhitpos.x][bhitpos.y].typ)
  262. #endif
  263.                                 ) {
  264.             drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
  265.             break;
  266.         }
  267.         tmp_at(bhitpos.x, bhitpos.y);
  268.     }
  269.     tmp_at(bhitpos.x, bhitpos.y);
  270.     tmp_at(-1, -1);
  271.     /* blindfold keeps substances out of your eyes */
  272.     if (blindinc && !Blindfolded) {
  273.         u.ucreamed += blindinc;
  274.         make_blinded(Blinded + blindinc,FALSE);
  275.     }
  276. }
  277.  
  278. #endif /* OVL1 */
  279. #ifdef OVLB
  280.  
  281. /* Remove an item from the monster's inventory.
  282.  */
  283. void
  284. m_useup(mon, obj)
  285. struct monst *mon;
  286. struct obj *obj;
  287. {
  288.     struct obj *otmp, *prev;
  289.  
  290.     if (obj->quan > 1) {
  291.         obj->quan--;
  292.         return;
  293.     }
  294.     prev = ((struct obj *) 0);
  295.     for (otmp = mon->minvent; otmp; otmp = otmp->nobj) {
  296.         if (otmp == obj) {
  297.             if (prev)
  298.                 prev->nobj = obj->nobj;
  299.             else
  300.                 mon->minvent = obj->nobj;
  301.             free((genericptr_t) obj);
  302.             break;
  303.         }
  304.         prev = otmp;
  305.     }
  306. }
  307.  
  308. #endif /* OVLB */
  309. #ifdef OVL1
  310.  
  311. /* Always returns 0??? -SAC */
  312. int
  313. thrwmu(mtmp)    /* monster throws item at you */
  314. register struct monst *mtmp;
  315. {
  316.     struct obj *otmp, *select_rwep();
  317.     register xchar x, y;
  318.  
  319.     if(lined_up(mtmp)) {
  320.  
  321.         if((otmp = select_rwep(mtmp))) {
  322.  
  323.         /* If you are coming toward the monster, the monster
  324.          * should try to soften you up with missiles.  If you are
  325.          * going away, you are probably hurt or running.  Give
  326.          * chase, but if you are getting too far away, throw.
  327.          */
  328.         x = mtmp->mx;
  329.         y = mtmp->my;
  330.         if(!URETREATING(x,y) ||
  331.            !rn2(BOLT_LIM-movedist(x,mtmp->mux,y,mtmp->muy)))
  332.         {
  333.             unsigned savequan = otmp->quan;
  334.             const char *verb = "throws";
  335.  
  336.             if (otmp->otyp == ARROW
  337. #ifdef TOLKIEN
  338.             || otmp->otyp == ELVEN_ARROW
  339.             || otmp->otyp == ORCISH_ARROW
  340. #endif
  341.             || otmp->otyp == CROSSBOW_BOLT) verb = "shoots";
  342.             otmp->quan = 1;
  343.             if (canseemon(mtmp))
  344.             pline("%s %s %s!", Monnam(mtmp), verb, an(xname(otmp)));
  345.             otmp->quan = savequan;
  346.             m_throw(mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), 
  347.             movedist(mtmp->mx,mtmp->mux,mtmp->my,mtmp->muy), otmp);
  348.             if (!otmp->quan) m_useup(mtmp, otmp);
  349.             nomul(0);
  350.             return 0;
  351.         }
  352.         }
  353.     }
  354.     return 0;
  355. }
  356.  
  357. #endif /* OVL1 */
  358. #ifdef OVLB
  359.  
  360. int
  361. spitmu(mtmp, mattk)        /* monster spits substance at you */
  362. register struct monst *mtmp;
  363. register struct attack *mattk;
  364. {
  365.     register struct obj *otmp;
  366.  
  367.     if(mtmp->mcan) {
  368.  
  369.         if(flags.soundok)
  370.         pline("A dry rattle comes from %s's throat", mon_nam(mtmp));
  371.         return 0;
  372.     }
  373.     if(lined_up(mtmp)) {
  374.         switch (mattk->adtyp) {
  375.             case AD_BLND:
  376.             case AD_DRST:
  377.             otmp = mksobj(BLINDING_VENOM, FALSE);
  378.             break;
  379.             default:
  380.             impossible("bad attack type in spitmu");
  381.                 /* fall through */
  382.             case AD_ACID:
  383.             otmp = mksobj(ACID_VENOM, FALSE);
  384.             break;
  385.         }
  386.         if(!rn2(BOLT_LIM-movedist(mtmp->mx,mtmp->mux,mtmp->my,mtmp->muy))) {
  387.             if (canseemon(mtmp))
  388.             pline("%s spits venom!", Monnam(mtmp));
  389.             m_throw(mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), 
  390.             movedist(mtmp->mx,mtmp->mux,mtmp->my,mtmp->muy), otmp);
  391.             nomul(0);
  392.             return 0;
  393.         }
  394.     }
  395.     return 0;
  396. }
  397.  
  398. #endif /* OVLB */
  399. #ifdef OVL1
  400.  
  401. int
  402. breamu(mtmp, mattk)            /* monster breathes at you (ranged) */
  403.     register struct monst *mtmp;
  404.     register struct attack  *mattk;
  405. {
  406.     if(lined_up(mtmp)) {
  407.  
  408.         if(mtmp->mcan) {
  409.         if(flags.soundok) {
  410.             if(canseemon(mtmp))
  411.             pline("%s coughs.", Monnam(mtmp));
  412.             else
  413.             You("hear a cough.");
  414.         }
  415.         return(0);
  416.         }
  417.         if(rn2(3)) {
  418.  
  419.         if((mattk->adtyp >= 1) && (mattk->adtyp < 11)) {
  420.  
  421.             if(canseemon(mtmp))
  422.             pline("%s breathes %s!", Monnam(mtmp),
  423.                   breathwep[mattk->adtyp-1]);
  424.             buzz((int) (-20 - (mattk->adtyp-1)), (int)mattk->damn,
  425.              mtmp->mx, mtmp->my, sgn(tbx), sgn(tby));
  426.             nomul(0);
  427.         } else impossible("Breath weapon %d used", mattk->adtyp-1);
  428.         }
  429.     }
  430.     return(1);
  431. }
  432.  
  433. boolean
  434. linedup(ax, ay, bx, by)
  435. register xchar ax, ay, bx, by;
  436. {
  437.     register xchar x, y;
  438.  
  439.     tbx = ax - bx;    /* These two values are set for use */
  440.     tby = ay - by;    /* after successful return.        */
  441.  
  442.     if((!tbx || !tby || abs(tbx) == abs(tby)) /* straight line or diagonal */
  443.        && movedist(tbx, 0,  tby, 0) < BOLT_LIM) {
  444.  
  445.         /* Check if there are any dead squares between.  If so,
  446.          * it will not be possible to shoot.
  447.          */
  448.         x = bx; y = by;
  449.         while(x != ax || y != ay) {
  450.  
  451.             if(!accessible(x, y)) return FALSE;
  452.             x += sgn(tbx), y += sgn(tby);
  453.         }
  454.         return TRUE;
  455.     }
  456.     return FALSE;
  457. }
  458.  
  459. boolean
  460. lined_up(mtmp)        /* is mtmp in position to use ranged attack? */
  461.     register struct monst *mtmp;
  462. {
  463.     return(linedup(mtmp->mux,mtmp->muy,mtmp->mx,mtmp->my));
  464. }
  465.  
  466. #endif /* OVL1 */
  467. #ifdef OVL0
  468.  
  469. /* Check if a monster is carrying a particular item.
  470.  */
  471. struct obj *
  472. m_carrying(mtmp, type)
  473. struct monst *mtmp;
  474. int type;
  475. {
  476.     register struct obj *otmp;
  477.  
  478.     for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
  479.         if(otmp->otyp == type)
  480.             return(otmp);
  481.     return((struct obj *) 0);
  482. }
  483.  
  484. #endif /* OVL0 */
  485. #ifdef OVL1
  486.  
  487. STATIC_OVL int
  488. movedist(x0, x1, y0, y1)
  489. int x0, x1, y0, y1;
  490. {
  491.     register int absdx, absdy;
  492.  
  493.     absdx = abs(x1 - x0);
  494.     absdy = abs(y1 - y0);
  495.  
  496.     return (max(absdx,absdy));
  497. }
  498.  
  499. #endif /* OVL1 */
  500.